﻿#include <Sys\RenderUnit\SysRenderDatagram\CONTROLATTRIBRD.HPP>
#include <Render\Render_Win32\Render_Win32_OpenGL\RENDER_WIN32_OPENGL.HPP>
#include <Sys\RenderUnit\SYSDDCLASSID.HPP>

using namespace CxxlMan;
using namespace Cxxl3D;

class CControlAttribDD_OpenGL:public IDatagramDisposal_OpenGL, public IControlAttribBridge
{
  class CControlAttrib_CEO:public IControlAttrib_CEO
  { 

    // 正反面剔除模式 Mode = 1:剔除正面  -1:剔除反面 -2:不剔除
    virtual void cxxlFASTCALL Cull(char CullMode)
    {
      switch(CullMode)
      {
      case 1:
        glEnable(GL_CULL_FACE);
        glCullFace(GL_BACK);
        break;
      case -1:
        glEnable(GL_CULL_FACE);
        glCullFace(GL_FRONT);
        break;
      case -2:
        glDisable(GL_CULL_FACE);
      }
    }

    // 多邊形填充模式 FillMode = 1:畫面  -1:畫線 -2:畫點
    virtual void cxxlFASTCALL Fill(char FillMode)
    {
      GLenum CMode;
      switch(FillMode)
      {
      case 1:
        CMode = GL_FILL;
        break;
      case -1:
        CMode = GL_LINE;
        break;
      case -2:
        CMode = GL_POINT;
      }
      glPolygonMode(GL_FRONT_AND_BACK, CMode);
    }


    // 是否使用內插(GL_SMOOTH) ShadeMode = true:是  false:否
    virtual void cxxlFASTCALL ShadeModel(bool ShadeMode)
    {
      if(ShadeMode)
        glShadeModel(GL_SMOOTH);
      else
        glShadeModel(GL_FLAT);
    }

    // 設定貼圖座標模式 Mode = 2:Repeat 1:Mirror -1:ClampEdge -2:ClampBorder
    /*
    virtual void TextureAddrMode(char Mode)
    {
      GLint mode;
      switch(Mode)
      {
      case 2:
        mode = GL_REPEAT;
        break;
      case 1:
        mode = GL_MIRRORED_REPEAT;
        break;
      case -1:
        mode = GL_CLAMP_TO_EDGE;
        break;
      case -2:
        mode = GL_CLAMP_TO_BORDER;
        break;
      }
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mode);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode);
    }
    */

    // TextureAddrMode() 指定為 ClampBorder 時，所用的顏色
    /*
    virtual void TextureClampBorderColor(char R, char G, char B, char A)
    {
      const float border_color[4] = {R/255.0f, G/255.0f, B/255.0f, A/255.0f};
      glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
    }
    */

    // 貼圖的 Mipmap 模式 Mode = 2:None 1:Bilinear -1:Trilinear -2:Anisotropic filter
    /*
    virtual void TextureMipmapMode(char Mode)
    {
      // 貼圖被放大時, 取最接近4個點來內插
      glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR );

      switch(Mode)
      {
      case 2:
        // 不使用 mipmap, 取最近 4 個點來平均
        glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        // 關閉 anisotrophic filter
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
        break;
      case 1:
        // GL_LINEAR = 貼圖縮小時取 4 個點來平均
        // MIPMAP_NEAREST = 使用最接近大小的圖層
        glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
        // 關閉 anisotrophic filter
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
        break;
      case -1:
        // GL_LINEAR = 貼圖縮小時取4個點來平均
        // MIPMAP_LINEAR = 使用最接近大小的兩張圖層, 然後再內插
        glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
        // 關閉anisotrophic filter
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
        break;
      case -2:
        // MIPMAP_LINEAR = 使用最接近大小的兩張圖層 , 然後再內插
        glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
        // 啟動 anisotrophic filter
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f);
      }
    }
    */

    // 是否為 Normalize 做正規化處理
    // Switch = true:是  false:否
    virtual void cxxlFASTCALL AutoNormalize(bool Switch) 
    {
      if ( Switch )
        glEnable(GL_NORMALIZE);
      else
        glDisable(GL_NORMALIZE);
    }



  public:
    CControlAttrib_CEO()
    {
    }
    virtual ~CControlAttrib_CEO(){}

  }Attrib_CEO;


  virtual bool cxxlFASTCALL Exec(const Smart_Ptr<IRenderDatagramDisposalCenterOpengl> &IRenderDatagramDisposalCenter_Arg,
    const Smart_Ptr<IRenderDatagram> &IRenderDatagram_Arg, const CxxlMan::CSmart_Ptr<Matrix4x4> &ViewMatrix_Arg)
  {
    if(actIControlAttribRD_Ptr.isNULL())
    {
      if(IRenderDatagram_Arg.isNULL() == false)
      {
        actIControlAttribRD_Ptr = (IControlAttribRD*)GetDefaultInterface(IRenderDatagram_Arg);
        SetAll(actIControlAttribRD_Ptr, &Attrib_CEO);
      }
    }
    else if(isModified(actIControlAttribRD_Ptr))
    {
      if(IRenderDatagram_Arg.isNULL() == false)
        actIControlAttribRD_Ptr = (IControlAttribRD*)GetDefaultInterface(IRenderDatagram_Arg);

      SetAll(actIControlAttribRD_Ptr, &Attrib_CEO);
    }
    else if(IRenderDatagram_Arg.isNULL() == false)
    {
      Smart_Ptr<IControlAttribRD> IControlAttribRD_Ptr = (IControlAttribRD*)GetDefaultInterface(IRenderDatagram_Arg);
      if((IControlAttribRD*)actIControlAttribRD_Ptr != (IControlAttribRD*)IControlAttribRD_Ptr)
      {
        Chk(actIControlAttribRD_Ptr, IControlAttribRD_Ptr, &Attrib_CEO);
        actIControlAttribRD_Ptr = IControlAttribRD_Ptr;
      }
    }

    return true;
  }


  Smart_Ptr<IControlAttribRD> actIControlAttribRD_Ptr;

public:
  // Consteructor
  CControlAttribDD_OpenGL()
    :cxxlObject(Spirit_Easy),
    actIControlAttribRD_Ptr(NULL,this)
  {
  }

  // Desteructor
  virtual ~CControlAttribDD_OpenGL()
  {
  }

};

cxxlObject *cxxlFASTCALL New_CControlAttribDD_OpenGL()
{
  return new CControlAttribDD_OpenGL;
}